﻿using MCUPackage;
using MCUPackage.Utils;
using SxPackages.STC8.DesignEditor;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace SxPackages.STC8.Models
{
	[Serializable]
	class SoftSPIOptions : SPIOptions
	{
		public override Boolean Enable
		{
			get => base.Enable;
			set
			{
				if (value != base.Enable)
				{
					if (value)
					{
						// 检查已经设置的引脚之间是否冲突
						if (TemplateHelper.PinsIsRepeat(mUsePins))
						{
							return;
						}
					}
					base.Enable = value;
				}
			}
		}

		[Browsable(false)]
		public override Boolean SSIG => true;
		[Browsable(false)]
		public override string Pins { get => base.Pins; set => base.Pins = value; }

		[Browsable(false)]
		public override Int32 Speed => 4;

		[Browsable(false)]
		public override Boolean EnableTI => false;
		[Browsable(false)]
		public override PriorityTypes Priority { get => base.Priority; set => base.Priority = value; }

		/// <summary>
		/// 切换引脚
		/// </summary>
		/// <param name="aNew"></param>
		/// <param name="aOld"></param>
		/// <param name="aPurpose"></param>
		/// <returns></returns>
		private bool SwitchPin(string aNew, string aOld, PinPurpose aPurpose)
		{
			if (this.Enable)
			{
				if (mParent.PinIsUsedTips(aNew))
				{
					return false;
				}
				mUsePins[aPurpose - PinPurpose.SOFT_SPI_SS] = aNew;
				SetPins(mUsePins);
				// 清除占用的功能脚
				mParent.ResetPins(aOld);
			}
			else
			{
				mUsePins[aPurpose - PinPurpose.SOFT_SPI_SS] = aNew;
			}
			return true;
		}

		private string mSS = string.Empty;
		/// <summary>
		/// 片选引脚
		/// </summary>
		[DisplayName("片选引脚"),
		Description("模拟SPI的片选引脚(SS)"),
		TypeConverter(typeof(PinsConvertor))]
		public string SS
		{
			get => mSS;
			set
			{
				if (value != mSS)
				{
					if (!SwitchPin(value, mSS, PinPurpose.SOFT_SPI_SS))
					{
						return;
					}
					mSS = value;
				}
			}
		}

		private string mMOSI = string.Empty;
		[DisplayName("主发从收引脚"),
		Description("模拟SPI的主发从收引脚选择(MOSI)"),
		TypeConverter(typeof(PinsConvertor))]
		public string MOSI
		{
			get => mMOSI;
			set
			{
				if (value != mMOSI)
				{
					if (!SwitchPin(value, mMOSI, PinPurpose.SOFT_SPI_MOSI))
					{
						return;
					}
					mMOSI = value;
				}
			}
		}

		private string mMISO = string.Empty;
		[DisplayName("主收从发引脚"),
		Description("模拟SPI的主收从发引脚选择(MISO)"),
		TypeConverter(typeof(PinsConvertor))]
		public string MISO
		{
			get => mMISO;
			set
			{
				if (value != mMISO)
				{
					if (!SwitchPin(value, mMISO, PinPurpose.SOFT_SPI_MISO))
					{
						return;
					}
					mMISO = value;
				}
			}
		}

		private string mSCLK = string.Empty;
		[DisplayName("时钟脚"),
		Description("模拟SPI的时钟引脚选择(SCLK)"),
		TypeConverter(typeof(PinsConvertor))]
		public string SCLK
		{
			get => mSCLK;
			set
			{
				if (value != mSCLK)
				{
					if (!SwitchPin(value, mSCLK, PinPurpose.SOFT_SPI_SCLK))
					{
						return;
					}
					mSCLK = value;
				}
			}
		}

		[Browsable(false)]
		public override Boolean CPHA => true;
		[Browsable(false)]
		public override Boolean CPOL => true;
		[Browsable(false)]
		public override Boolean Master => true;
		[Browsable(false)]
		public override Boolean MSB => true;

		protected override void SetPins(String[] aPins)
		{
			base.SetPins(aPins);
			var purpose = PinPurpose.SOFT_SPI_SS;
			for (int i = 0; i < 4; i++)
			{
				mParent.SetPinPurpose(aPins[i], purpose, false);
				purpose++;
			}
		}

		/// <summary>
		/// 设置的引脚是否有效
		/// </summary>
		/// <returns></returns>
		public bool PinsValid()
		{
			foreach (var pin in mUsePins)
			{
				if (mParent.GetPin(pin) == null)
				{
					return false;
				}
			}

			return true;
		}

		public SoftSPIOptions(STC8HUSOP20 aParent) : base(aParent)
		{
			this.Type = SPITypes.SOFT;
			mUsePins = new string[] { SS, MOSI, MISO, SCLK };
		}

		public override Boolean AppendConfig(List<String[]> aLst)
		{
			return false;
		}
		/// <summary>
		/// SPI的引脚名集合
		/// </summary>
		private static readonly string[] SPI_NAMES = new string[] { "SPI_CS", "SPI_MOSI", "SPI_MISO", "SPI_SCK" };

		/// <summary>
		/// 创建需要的库文件
		/// </summary>
		/// <param name="aPath"></param>
		/// <param name="aPins"></param>
		/// <returns></returns>
		public bool CreateLibFiles(string aPath)
		{
			string file = "STC32G_Soft_SPI.h";
			var pairs = TemplateHelper.CreatePairs();

			for (int i = 0; i < SPI_NAMES.Length; i++)
			{
				pairs[SPI_NAMES[i]] = mParent.GetPin(mUsePins[i]) == null ? "P66" : mUsePins[i].Replace(".", "");
			}

			return mParent.CreateByTemplate(PathTypes.Drivers_STC_Inc, aPath, file, false, pairs);
		}

		/// <summary>
		/// 获取模拟SPI配置
		/// </summary>
		/// <param name="aPath"></param>
		/// <returns>初始化函数</returns>
		public bool AppendConfig(string aPath, List<String[]> aLst)
		{
			if (!this.Enable)
			{
				return false;
			}

			Dictionary<string, List<string>> lst = new Dictionary<string, List<string>>();
			foreach (var pin in mUsePins)
			{
				var opt = mParent.GetPinOption(pin);
				if (opt != null)
				{
					opt.ToSTC8Dictionary(lst);
				}
			}
			if (lst.Count < 4)
			{
				// 未设置引脚
				return false;
			}

			if (!CreateLibFiles(aPath))
			{
				return false;
			}

			string name = "SoftSPI_Config";
			StringBuilder funcSb = new StringBuilder();
			funcSb.Append(TemplateHelper.GetFunctionCommit("模拟SPI模块初始化"));
			funcSb.AppendLine($"PRIVATE void {name}(void)").AppendLine("{");

			funcSb.Append(GPIOOptions.GetGPIOConfigs(lst));
			funcSb.AppendLine();
			funcSb.AppendLine("\tSoftSPI_Init();");
			funcSb.AppendLine("}");
			aLst.Add(new string[] { funcSb.ToString(), $"{name}();" });

			return true;
		}
	}
}
